/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bgu.dcr.tp.sim;

import bgu.dcr.tp.api.Behavior;
import bgu.dcr.tp.api.World;
import bgu.dcr.tp.api.sim.EntitySelector;
import bgu.dcr.tp.api.sim.EntitySelectorHandler;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Shl
 */
public class SimpleSelector implements EntitySelector, World.WorldListener {

    private EntitySelectorHandler handler;
    private World world;
    private Map<Integer, List<Behavior>> behaviorMap;

    @Override
    public void initialize(World w, EntitySelectorHandler handler) {
        this.handler = handler;
        this.world = w;
        this.behaviorMap = new HashMap<>();
        Collection<Integer> idList = world.getAllIds();
        for (Integer id : idList) {
            behaviorMap.put(id, new LinkedList<Behavior>());
        }
        Collection<Behavior> behaviors = world.getBehaviors();
        for (Behavior b : behaviors) {
            Class[] requirement = b.getRequirement();
            for (Integer id : idList) {
                boolean allreqs = true;
                for (Class data : requirement) {
                    if (world.getData(id, data) == null) {
                        allreqs = false;
                        break;
                    }
                }
                if (allreqs) {
                    behaviorMap.get(id).add(b);
                }
            }
        }
        world.getListeners().add(this);
    }

    @Override
    public void select() {
        for (Map.Entry<Integer, List<Behavior>> idEntry : behaviorMap.entrySet()) {
            for (Behavior b : idEntry.getValue()) {
                handler.handle(idEntry.getKey(), b);
            }
        }
    }

    @Override
    public void onDataAdded(World source, int index, Object data) {
    }

    @Override
    public void onIndexAdded(World source, int index) {
        Collection<Behavior> behaviors = source.getBehaviors();
        behaviorMap.put(index, new LinkedList<Behavior>());
        for (Behavior b : behaviors) {
            Class[] requirement = b.getRequirement();
            boolean allreqs = true;
            for (Class data : requirement) {
                if (world.getData(index, data) == null) {
                    allreqs = false;
                    break;
                }
            }
            if (allreqs) {
                behaviorMap.get(index).add(b);
            }
        }
    }

    @Override
    public void onBehaviorAdded(World source, Behavior b) {
        Class[] requirement = b.getRequirement();
        for (Map.Entry<Integer, List<Behavior>> idEntry : behaviorMap.entrySet()) {
            boolean allreqs = true;
            for (Class data : requirement) {
                if (world.getData(idEntry.getKey(), data) == null) {
                    allreqs = false;
                    break;
                }
            }
            if (allreqs) {
                behaviorMap.get(idEntry.getKey()).add(b);
            }
        }
    }

    
    /**
     * need to override behavior equals and hash for remove to work.
     */
    @Override
    public void onBehaviorRemoved(World source, Behavior b) {
        for (Map.Entry<Integer, List<Behavior>> idEntry : behaviorMap.entrySet()) {
            List<Behavior> behaviorList = idEntry.getValue();
            if (behaviorList.contains(b)) {
                behaviorList.remove(b);
            }
        }
    }
}
